﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using WW.NActiveRecord.Internal;


namespace WW.NActiveRecord.Tests.StudyTest
{
    public class TestReflection {

        [Test]
        public void TestMethodInvokeStackTrace() {
            MethodInvokeStackTrace.HasMany("方法");
           
        }
        class MethodInvokeStackTrace {
            private string s = HasMany("字段");
            internal static string HasMany(string s) {
                Debug2.Print(s);
                Debug2.Print(new StackTrace().GetFrames().Select(x => x.GetMethod()));
                return "";
            }
            public MethodInvokeStackTrace() {
                HasMany("构造器");
            }
        }

        public void TestTypeAndObject()
        {
            BContainer b=new BContainer();
            b.Print();
            Console.WriteLine(b.func.Target);

            Assert.IsTrue(typeof(object).IsInstanceOfType(1));
            Assert.IsTrue(typeof(IList).IsInstanceOfType(new ArrayList()));
            Assert.IsTrue(typeof(IList<int>).IsInstanceOfType(new List<int>()));
            Assert.IsTrue(typeof(ICollection).IsInstanceOfType(new List<int>()));

            Assert.IsTrue(typeof(string).IsInstanceOfType(""));
            Assert.IsFalse(typeof(List<>).IsInstanceOfType(new List<int>()));
            Assert.IsTrue(typeof(List<int>).IsInstanceOfType(new List<int>()));

        }



        public void TestTypeAndType()
        {
            Assert.IsTrue(typeof(ICollection).IsAssignableFrom(typeof(ReadOnlyCollection<>)));
            Assert.IsTrue(typeof(ICollection).IsAssignableFrom(typeof(ReadOnlyCollection<int>)));
            Assert.IsTrue(typeof(object).IsAssignableFrom(typeof(ReadOnlyCollection<>)));

            Assert.IsFalse(typeof(IList<int>).IsAssignableFrom(typeof(IList<>)));
            Assert.IsFalse(typeof(KeyedCollection<,>).IsSubclassOf(typeof(Collection<>)));
            Assert.IsFalse(typeof(Collection<int>).IsSubclassOf(typeof(ICollection<int>)));

            Assert.IsTrue(typeof(IList<int>).IsAssignableFrom(typeof(ReadOnlyCollection<int>)));
            Assert.IsFalse(typeof(IList<>).IsAssignableFrom(typeof(ReadOnlyCollection<>)));

            
            Assert.IsFalse(typeof(ReadOnlyCollection<>).IsSubclassOf(typeof(ICollection<>)));

            Console.WriteLine(typeof(IDictionary<,>).Name);
            Console.WriteLine(typeof(List<int>).GetInterface("System.Collections.Generic.IList`1", true));
            
        }
        public void Test继承()
        {
            
        }
        public void TestField()
        {
            FieldInfo f = this.GetType().GetField("field");
            Assert.IsFalse(f.IsInitOnly);
            Console.WriteLine(f.FieldType);
            Console.WriteLine(f.FieldType.GetGenericTypeDefinition());

            Assert.IsTrue(typeof(ICollection).IsAssignableFrom(f.FieldType));
            Assert.IsTrue(typeof(ICollection).IsAssignableFrom(f.FieldType.GetGenericTypeDefinition()));
            Assert.IsFalse(typeof(ICollection<>).IsAssignableFrom(f.FieldType.GetGenericTypeDefinition()));
            Assert.IsFalse(typeof(ICollection<>).IsAssignableFrom(f.FieldType));
            Assert.IsFalse(f.FieldType == typeof(List<>));
            Assert.IsTrue(f.FieldType.GetGenericTypeDefinition() == typeof(List<>));



        }
        public List<int> field=new List<int>();

        public void TestStatic()
        {
            AA.AMethod();
        }
        class ABase
        {
            static ABase() {
                Console.WriteLine("static ABase");
            }
            public static void XX() { }
        }
        class A<T>:ABase {

            static A() {
                Console.WriteLine("static A "+typeof(T).Name);
            }
            public A()
            {
                Console.WriteLine("A " + typeof(T).Name);
            }
            
        }
        class AA : A<AA> {
            public static void AMethod() { }
        }
        class BB<T> : A<T> {

        }
    }

    public class BContainer
    {
        public Func<string> func=new Func<string>(()=>"");
        public void Print()
        {
            Console.WriteLine(func.Target);
        }
        public B CreateB()
        {
            return new B(this);
        }

        public string X
        {
            set
            {
                StackTrace st = new StackTrace(false);
                StackFrame sf = st.GetFrame(1);
                Console.WriteLine(sf.GetMethod().ReflectedType.Name);
            }
        }
    }

    public class B {
        private BContainer c;
 
        public B(BContainer c)
        {
            this.c = c;
        }
    }
}